<template>
    <el-upload
        class="upload-custom"
        :class="{headImg: headImg}"
        ref="upload"
        v-loading="loading"
        :action="$staticUrl"
        :file-list="fileList"
        :accept="accept"
        :data="uploadData"
        :show-file-list="!isSingle && !customList"
        :before-upload="_beforeUpload"
        :on-preview="onPreview"
        :on-remove="onRemove"
        :on-success="onSuccess">
        <template v-if="headImg">
            <img v-if="imageUrl" :src="imageUrl" class="avatar">
            <i v-else class="el-icon-plus avatar-uploader-icon"></i>
        </template>
        <img v-else-if="imageUrl && isSingle" :src="imageUrl" class="avatar">
        <template v-else-if="!customList">
            <div class="el-upload-dragger">
                <i class="el-icon-upload"></i>
                <!--<div class="el-upload__text">将文件拖到此处，或<em>点击上传</em></div>-->
                <div class="el-upload__text">点击上传</div>
            </div>
        </template>
        <template v-else>
            <el-button slot="trigger" size="small" type="primary">点击上传</el-button>
            <ul class="custom-file-list">
                <template v-for="(item, index) in sourceList" >
                    <li :key="index" @click="previewFile(item)">
                        <span class="name"><icon-svg name="icon-upload-file"></icon-svg>{{ item.url | getName }}</span>
                        <span class="btn">
                            <img class="success" src="~@/assets/file-success.png" alt="">
                            <img class="delete" src="~@/assets/file-delete.png" alt="" @click.stop="deleteFile(item)">
                        </span>
                    </li>
                </template>
            </ul>
        </template>
    </el-upload>
</template>

<script lang="ts">
import { Component, Mixins, Prop, Watch } from "vue-property-decorator";
import { getUUID } from "@/utils";
import AuthMixin from "@/components/upload-cos/auth.mixin";
import { dialogPreviewVideoAudio } from '@/components/public/preview-video-audio/index';

@Component({
    name: "UpLoadCos",
    filters: {
        getName(val: any) {
            if (!val.includes("?")) return val;
            const params = val.split("?")[1].split("&");
            const obj: any = {};
            params.forEach((item: any) => {
                obj[item.split("=")[0]] = item.split("=")[1];
            });
            return obj.name;
        }
    }
})
export default class UpLoadCos extends Mixins(AuthMixin) {
    // 上传前自定义
    @Prop({
        type: Function,
        default: () => {
            return Promise.resolve(true);
        }
    })
    readonly beforeUpload!: any;

    // 限制类型
    @Prop({
        type: String,
        default: () => {
            return "*";
        }
    })
    readonly accept!: any;

    // 单文件上传，不需要文件列表
    @Prop({
        type: Boolean,
        default: false
    })
    readonly isSingle!: boolean;

    // 自定义文件列表
    @Prop({
        type: Boolean,
        default: false
    })
    readonly customList!: boolean;

    // 头像上传那种样式
    @Prop({
        type: Boolean,
        default: false
    })
    readonly headImg!: boolean;

    // 文件列表
    @Prop({
        type: Array,
        default: () => {
            return [];
        }
    })
    readonly list!: any[];

    @Watch("list", { deep: true })
    changeList() {
        this.initList();
    }

    // 上传数量
    @Prop({
        type: Number,
        default: 9
    })
    readonly limit!: number;

    // 功能种类
    @Prop({
        type: String,
        required: true
    })
    readonly type!: string;

    // 文件类型
    @Prop({
        type: String,
        required: true
    })
    readonly fileType!: string;

    uploadData: any = {
        signature: '',
        "x-cos-security-token": "",
        "Content-Type": "",
        key: "",
        dir: "",
        host: ""
    };

    fileList: any[] = []

    path = ""
    imageUrl = ""

    sourceList: any[] = [];
    loading = false

    created() {
        this.initList();
    }

    initList() {
        this.fileList = [];
        this.sourceList = [];
        this.list.forEach((item: any) => {
            this.fileList.push({
                name: Object.prototype.toString.call(item) === '[object Object]' ? item.url : item,
                url: this.$staticUrl + "/" + (Object.prototype.toString.call(item) === '[object Object]' ? item.url : item)
            });
        });
        this.$nextTick(() => {
            this.sourceList = this.fileList.map((item: any) => {
                return {
                    ...item,
                    _id: item.uid,
                    url: item.name,
                    host: this.$staticUrl
                };
            });
        });
        if (this.headImg && this.isSingle && this.fileList.length) {
            this.imageUrl = this.fileList[0].url;
        }
    }

    async onSuccess(res: any, file: any) {
        const fileName = file.name.replace(/[,，]/g, '');
        this.sourceList.push({
            _id: file.uid,
            url: this.uploadData.key + "?name=" + fileName,
            host: this.uploadData.host
        });
        this.imageUrl = URL.createObjectURL(file.raw);
        this.$emit("onUpdate", this.sourceList);
        this.loading = false;
    }

    onRemove(file: any) {
        const index = this.sourceList.findIndex((item: any) => item._id === file.uid);
        if (index !== -1) {
            this.sourceList.splice(index, 1);
            this.$emit("onUpdate", this.sourceList);
        }
    }

    _beforeUpload(file: any) {
        if (this.isSingle) this.sourceList = [];
        if (this.sourceList.length === this.limit) {
            this.$message.error(`最多允许上传${this.limit}个文件`);
            return false;
        }
        return new Promise((resolve: any, reject: any) => {
            const uploadPolicy = () => {
                const videoList = ['mp4', 'm2v', 'mkv', 'rmvb', 'wmv', 'avi', 'flv', 'mov', 'm4v'];
                const radioList = ["wmv", "act", "rec", "vy1", "vy2", "vy3", "vy4", "sc4", "dvf", "msc", "wma", "mp3", "wav", "aiff", "ava", "m4a"];
                const imgList = ["bmp", "jpg", "jpeg", "png", "gif"];
                const docList = ["txt", "pdf", "doc", "docx", "xls", "xlsx", "ppt", "pptx", "htm", "html", "xml", "psd", "wps", "reg", "bat", "tmp", "log"];
                const arr = file.name.split(".");
                const fileType = arr[arr.length - 1];
                const type = videoList.includes(fileType) ? "video" : radioList.includes(fileType) ? "audio" : imgList.includes(fileType) ? "img" : docList.includes(fileType) ? "doc" : "other";

                const _path = `/${this.type}/${type}/${new Date().format("yyyy-MM-dd")}/${this.path}`;
                this.getAuthorization({ Method: 'POST', Pathname: '/' })
                    .then((info: any) => {
                        this.uploadData.signature = info.Authorization;
                        this.uploadData['x-cos-security-token'] = info.XCosSecurityToken;
                        this.uploadData['Content-Type'] = "";
                        this.uploadData.key = _path + getUUID() + "." + fileType;
                        this.uploadData.dir = _path;
                        this.uploadData.host = this.$staticUrl;
                        this.loading = true;
                        resolve(true);
                    })
                    .catch((err: any) => {
                        this.$message.error({
                            message: err.message || err.content || "接口请求失败",
                            type: "error",
                            duration: 1500
                        });
                        return reject(new Error(err));
                    });
            };
            this.beforeUpload(file).then((r: boolean) => {
                if (r) {
                    const maxSize = 100 * 1024 * 1024;
                    if (file.size > maxSize) {
                        this.$message.error("上传文件大小请勿超过100M!");
                    } else {
                        uploadPolicy();
                    }
                }
            });
        });
    }

    onPreview(file: any) {
        let url = "";
        if (file.url) {
            url = file.url;
        } else {
            const cur = this.sourceList.filter((item: any) => item._id === file.uid);
            if (cur.length) {
                url = cur[0].host + "/" + cur[0].url;
            }
        }
        dialogPreviewVideoAudio({
            sourceUrl: url
        });
    }

    // 自定义预览
    previewFile(file: any) {
        dialogPreviewVideoAudio({
            sourceUrl: file.host + "/" + file.url
        });
    }

    // 删除文件
    deleteFile(item: any) {
        const indexS = this.sourceList.findIndex((fileItem: any) => fileItem._id === item._id);
        const indexF = this.fileList.findIndex((fileItem: any) => fileItem._id === item._id);
        if (indexS !== -1) {
            this.sourceList.splice(indexS, 1);
        }
        if (indexF !== -1) {
            this.fileList.splice(indexF, 1);
        }
        this.$emit("onUpdate", this.sourceList);
    }
}
</script>

<style lang="scss" scoped>
    .upload-custom {
        max-width: 500px;
    }
    .custom-file-list {
        @include flexLayout(flex,normal,normal);
        flex-wrap: wrap;
        margin-top: 10px;
        max-height: 110px;
        overflow-y: auto;
        li {
            width: calc(50% - 10px);
            cursor: pointer;
            background: #FFFFFF;
            box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.1);
            opacity: 1;
            border-radius: 4px;
            margin-right: 20px;
            margin-bottom: 10px;
            padding: 10px 8px;
            @include flexLayout(flex,justify,center);
            &:nth-child(2n) {
                margin-right: 0;
            }
            span {
                display: inline-block;
            }
            .name {
                font-size: 14px;
                font-family: "PingFang SC Medium";
                line-height: 20px;
                color: #37383a;
                width: calc(100% - 20px);
                @include textEllipsis();
                .icon-svg {
                    margin-right: 5px;
                }
            }
            .btn {
                img {
                    display: block;
                    width: 16px;
                    height: 16px;
                    &.delete {
                        display: none;
                    }
                }
            }
            &:hover {
                .btn {
                    .success {
                        display: none;
                    }

                    .delete {
                        display: block;
                    }
                }
            }
        }
    }
    .upload-custom.headImg {
        ::v-deep {
            .el-upload {
                border: 1px dashed #d9d9d9;
                border-radius: 6px;
                cursor: pointer;
                position: relative;
                overflow: hidden;
                display: block;
                width: 100px;
                &:hover {
                    border-color: #409EFF;
                }
            }
        }
    }
    .avatar-uploader-icon {
        font-size: 28px;
        color: #8c939d;
        width: 100px;
        height: 100px;
        line-height: 100px;
        text-align: center;
    }
    .avatar {
        width: 100px;
        height: 100px;
        display: block;
        object-fit: contain;
    }
</style>
